home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
editor
/
j414src.arc
/
JOVE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-10
|
29KB
|
1,440 lines
/***************************************************************************
* This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
* is provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
***************************************************************************/
/* Contains the main loop initializations, and some system dependent
type things, e.g. putting terminal in CBREAK mode, etc. */
#include "jove.h"
#include "fp.h"
#include "termcap.h"
#include "ctype.h"
#include "chars.h"
#include "disp.h"
#include "re.h" /* for find_tag() */
#include "rec.h"
#if defined(IPROCS)
# include "iproc.h"
#endif
#ifdef MAC
# include "mac.h"
#else
# ifdef STDARGS
# include <stdarg.h>
# else
# include <varargs.h>
# endif
# include <sys/stat.h>
#endif
#include <signal.h>
#include <errno.h>
#ifdef UNIX
# ifndef SYSV
# include <sgtty.h>
# else
# include <termio.h>
# endif /* SYSV */
#endif /* UNIX */
#ifdef MSDOS
# include <process.h>
#endif /* MSDOS */
#ifndef MAC
# include <fcntl.h>
#endif
#ifdef MSDOS
extern time_t time proto((time_t *));
private void break_off proto((void)),
break_rst proto((void));
#endif
private void
DoKeys proto((int firsttime)),
UNIX_cmdline proto((int argc,char * *argv));
#ifdef MSDOS
extern void UnsetTerm proto((char *));
#else
private void UnsetTerm proto((char *));
#endif
/* Various tty state structures.
* Each is an array, subscripted by one of "OFF" or "ON".
*/
#ifndef MAC
#include "ttystate.h"
#endif
#ifdef UNIX
# ifdef TIOCSLTC
struct ltchars ls[2];
# endif /* TIOCSLTC */
# if defined(TIOCGETC) && !defined(SYSV)
struct tchars tc[2];
# endif
# ifdef PASS8 /* use pass8 instead of raw for meta-key */
private int lmword[2]; /* local mode word */
# endif
# ifdef BRLUNIX
struct sg_brl sg[2];
# else
# ifdef SYSV
struct termio sg[2];
# else /* SYSV */
struct sgttyb sg[2];
# endif /* SYSV */
# endif /* BRLUNIX */
# ifdef BIFF
private struct stat tt_stat; /* for biff */
# ifndef BSD4_2
private char *tt_name = 0; /* name of the control tty */
extern char *ttyname(); /* for systems w/o fchmod ... */
# endif
private int dw_biff = NO; /* whether or not to fotz at all */
# endif /* BIFF */
#endif /* UNIX */
int errormsg;
char NullStr[] = "";
jmp_buf mainjmp;
#ifdef MSDOS
# define SIGHUP 99
#endif /* MSDOS */
/* finish() does not return, so it is funny that it returns a non-void
* result. This is because most systems claim that signal(2) deals
* with functions of type int (). ANSI changes this: the function
* type must be void (int). This bridge must soon be crossed.
*/
SIGRESULT
finish(code)
int code;
{
int CoreDump = (code != 0 && code != SIGHUP),
DelTmps = 1; /* Usually we delete them. */
if (code == SIGINT) {
char c;
#if defined(IPROCS) && defined(PIPEPROCS)
int started;
#endif
#ifndef MENLO_JCL
(void) signal(code, finish);
#endif
f_mess("Abort (Type 'n' if you're not sure)? ");
#ifndef MSDOS
# if defined(IPROCS) && defined(PIPEPROCS)
started = kbd_stop();
# endif
#ifdef SYSV
if (read(0, &c, (size_t) 1) != 1)
#endif
(void) read(0, &c, (size_t) 1);
# if defined(IPROCS) && defined(PIPEPROCS)
if (started)
(void) kbd_strt();
# endif
#else /* MSDOS */
c = getrawinchar();
#endif /* MSDOS */
message(NullStr);
if ((c & 0377) != 'y') {
redisplay();
SIGRETURN;
}
}
DisabledRedisplay = YES;
#ifndef MAC
UnsetTerm(NullStr);
#endif
#if defined(IPROCS) && defined(PIPEPROCS)
kbd_kill(); /* kill the keyboard process */
#endif
#ifndef MSDOS
if (code != 0) {
if (!Crashing) {
Crashing = YES;
lsave();
SyncRec();
writef("JOVE CRASH!! (code %d)\n", code);
if (ModBufs(1)) {
writef("Your buffers have been saved.\n");
writef("Use \"jove -r\" to have a look at them.\n");
DelTmps = 0; /* Don't delete anymore. */
} else
writef("You didn't lose any work.\n");
} else
writef("\r\nYou may have lost your work!\n");
}
#endif /* MSDOS */
flusho();
if (DelTmps) {
#if defined(IPROCS) && !defined(PIPEPROCS)
(void) signal(SIGCHLD, SIG_IGN);
#endif
tmpclose();
#ifndef MSDOS
recclose();
#endif /* MSDOS */
}
#ifdef UNIX
if (CoreDump)
abort();
#ifdef PROFILING
exit(0);
#else
_exit(0);
#endif
#else /* MSDOS or MAC*/
#ifdef MSDOS
break_rst(); /* restore previous ctrl-c handling */
#endif
exit(0);
#endif /* UNIX */
/*NOTREACHED*/
}
private char smbuf[20],
*bp = smbuf;
private int nchars = 0;
private char peekbuf[10],
*peekp = peekbuf;
#if defined(SYSV) || defined(M_XENIX)
void
setblock(fd, on) /* turn blocking on or off */
register int fd, on;
{
static int blockf, nonblockf;
static int first = 1;
int flags;
if (first) {
first = 0;
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
finish(SIGHUP);
blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */
nonblockf = flags | O_NDELAY; /* make sure O_NDELAY is on */
}
if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
finish(SIGHUP);
}
#endif /* SYSV */
private int
Peekc()
{
int c;
if (peekp == peekbuf)
c = EOF;
else
c = *--peekp & 0377;
return c;
}
void
Ungetc(c)
int c;
{
if (peekp == &peekbuf[(sizeof peekbuf) - 1])
return; /* Sorry, can't oblige you ... */
*peekp++ = c;
}
int InputPending = 0;
char *Inputp = 0;
#if (defined(IPROCS) && !defined(PIPEPROCS)) /* that is, if ptys */
int
jgetchar()
{
long reads;
register int tmp,
nfds;
int c;
if (nchars <= 0) {
/* Get a character from the keyboard, first checking for
any input from a process. Handle that first, and then
deal with the terminal input. */
do {
do {
reads = global_fd;
nfds = select(32, &reads, (long *) 0, (long *) 0, (struct timeval *) 0);
} while (nfds < 0 && errno == EINTR);
if (nfds == -1)
complain("\rerror %d in select %ld", errno, global_fd);
else {
if (reads & 01) {
nchars = read(0, smbuf, sizeof(smbuf));
reads &= ~01;
nfds -= 1;
}
while (nfds--) {
tmp = ffs(reads) - 1;
read_proc(tmp);
reads &= ~(1L << tmp);
}
}
} while (nchars <= 0);
if (nchars <= 0)
finish(SIGHUP);
bp = smbuf;
InputPending = (nchars > 1);
}
if (((c = *bp) & 0200) && MetaKey != 0) {
*bp = (c & CHARMASK);
return '\033';
}
nchars -= 1;
return *bp++ & 0377;
}
#else
jgetchar()
{
register int c;
struct header {
int pid;
int nbytes;
} header;
int n;
normal:
if (nchars <= 0) {
bp = smbuf;
#ifdef MSDOS
*bp = getrawinchar();
nchars = 1;
#else
# ifdef IPROCS
if (NumProcs == 0) {
# endif
do
nchars = read(0, smbuf, sizeof smbuf);
# ifdef SYSV
while (nchars == 0 || (nchars < 0 && errno == EINTR));
if (nchars < 0)
# else
while (nchars < 0 && errno == EINTR);
if (nchars <= 0)
# endif /* SYSV */
finish(SIGHUP);
# ifdef IPROCS
} else for (;;) {
n = f_readn(ProcInput, &header, sizeof (header));
if (n == EOF) {
printf("\rError reading kbd process.\n");
finish(1);
}
/* data is from the keyboard process */
if (header.pid == kbd_pid) {
nchars = f_readn(ProcInput, smbuf, header.nbytes);
if (nchars != header.nbytes) {
printf("\rError reading kbd process.");
finish(1);
} else
break;
} else
read_proc(header.pid, header.nbytes);
if (NumProcs == 0) {
(void) kbd_stop();
goto normal;
}
}
# endif /* IPROCS */
#endif /* MSDOS */
InputPending = nchars > 0;
}
if (((c = *bp) & 0200) && MetaKey != 0) {
*bp = (c & CHARMASK);
return '\033';
}
nchars -= 1;
return (*bp++ & CHARMASK);
}
#endif /* IPROCS */
/* Returns non-zero if a character waiting */
int
charp()
{
int some = 0;
if (InJoverc != 0 || nchars > 0 || Inputp != 0)
return 1;
#ifdef BRLUNIX
{
static struct sg_brl gttyBuf;
gtty(0, (char *) >tyBuf);
if (gttyBuf.sg_xflags & INWAIT)
some += 1;
}
#endif
#ifdef FIONREAD
{
long c;
if (ioctl(0, FIONREAD, (UnivPtr) &c) == -1)
c = 0;
some = (c > 0);
}
#endif /* FIONREAD */
#if defined(SYSV) || defined(M_XENIX)
setblock(0, 0); /* turn blocking off */
nchars = read(0, smbuf, sizeof smbuf); /* Is anything there? */
setblock(0, 1); /* turn blocking on */
if (nchars > 0) /* something was there */
bp = smbuf; /* make sure bp points to it */
some = (nchars > 0); /* just say we found something */
#endif /* SYSV */
#ifdef c70
some = !empty(0);
#endif
#ifdef MSDOS
some = rawkey_ready();
#endif
#ifdef MAC
some = rawchkc();
#endif
return some;
}
void do_sgtty proto((void));
#ifdef BIFF
private void biff_init proto((void));
#endif
#ifdef TERMCAP
private void
ResetTerm()
{
do_sgtty(); /* this is so if you change baudrate or stuff
like that, JOVE will notice. */
ttyset(ON);
putpad(TI, 1);
putpad(VS, 1);
putpad(KS, 1);
#ifdef UNIX
(void) chkmail(YES); /* force it to check to we can be accurate */
#endif
#ifdef BIFF
if (BiffChk != dw_biff)
biff_init();
/* just in case we changed our minds about whether to deal with
biff */
#endif
}
private void
UnsetTerm(mesg)
char *mesg;
{
ttyset(OFF);
#ifdef ID_CHAR
INSmode(0);
#endif
putpad(KE, 1);
putpad(VE, 1);
/*
* For terminals without an alternate page, go the bottom of the
* screen. Alternate page - just return to the original place on
* the screen
*/
if (!TE) {
Placur(ILI, 0);
putpad(CE, 1);
} else {
putpad(TE, 1);
}
if (mesg[0] != '\0')
writef("%s\n", mesg);
flusho();
}
#endif /* TERMCAP */
#ifdef JOB_CONTROL
void
PauseJove()
{
UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
(void) kill(0, SIGTSTP);
ResetTerm();
ClAndRedraw();
}
#endif
#ifndef MAC
void
Push()
{
#ifndef MSDOS
int pid;
SIGRESULT (*old_quit) proto((int)) = signal(SIGQUIT, SIG_IGN);
#endif /* MSDOS */
SIGRESULT (*old_int) proto((int)) = signal(SIGINT, SIG_IGN);
#ifndef MSDOS
#ifdef IPROCS
SigHold(SIGCHLD);
#endif
#if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
SigHold(SIGWINCH);
#endif
alarm(0);
switch (pid = fork()) {
case -1:
complain("[Fork failed]");
/*NOTREACHED*/
case 0:
UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
#if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
SigRelse(SIGWINCH);
#endif
#ifdef IPROCS
SigRelse(SIGCHLD);
#endif
(void) signal(SIGTERM, SIG_DFL);
#else /* MSDOS */
UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
#endif /* MSDOS */
(void) signal(SIGINT, SIG_DFL);
#ifdef UNIX
(void) signal(SIGQUIT, SIG_DFL);
execl(Shell, basename(Shell), "-i", (char *)0);
message("[Execl failed]");
_exit(1);
}
#ifdef IPROCS
SigRelse(SIGCHLD);
#endif
dowait(pid, (int *) 0);
#endif /* UNIX */
#ifdef MSDOS
break_rst();
if (spawnl(0, Shell, basename(Shell), (char *)0) == -1)
message("[Spawn failed]");
#endif /* MSDOS */
#ifndef MAC
ResetTerm();
#endif
#if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(SigRelse)
SigRelse(SIGWINCH);
#endif
ClAndRedraw();
#ifndef MSDOS
(void) signal(SIGQUIT, old_quit);
#else /* MSDOS */
break_off();
getCWD();
#endif /* MSDOS */
(void) signal(SIGINT, old_int);
#ifndef MSDOS
(void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
#endif
}
#endif /* MAC */
int OKXonXoff = 0, /* ^S and ^Q initially DON'T work */
IntChar = CTL(']');
private void
ttsize()
{
#ifdef UNIX
# ifdef TIOCGWINSZ
struct winsize win;
if (ioctl (0, TIOCGWINSZ, (UnivPtr) &win) == 0) {
if (win.ws_col)
CO = win.ws_col;
if (win.ws_row)
LI = win.ws_row;
}
# else /* TIOCGWINSZ */
# ifdef BTL_BLIT
#include <sys/jioctl.h>
struct jwinsize jwin;
if (ioctl(0, JWINSIZE, &jwin) == 0) {
if (jwin.bytesx)
CO = jwin.bytesx;
if (jwin.bytesy)
LI = jwin.bytesy;
}
# endif /* BTL_BLIT */
# endif /* TIOCGWINSZ */
#endif /* UNIX */
#ifdef MAC
CO = getCO(); /* see mac.c */
LI = getLI();
Windchange = 1;
clr_page();
#endif
ILI = LI - 1;
}
#ifdef BIFF
private void
biff_init()
{
dw_biff = ((BiffChk) &&
# ifndef BSD4_2
((tt_name != 0) || (tt_name = ttyname(0))) &&
(stat(tt_name, &tt_stat) != -1) &&
# else
(fstat(0, &tt_stat) != -1) &&
# endif
(tt_stat.st_mode & S_IEXEC)); /* he's using biff */
}
private void
biff(on)
int on;
{
if (dw_biff == NO)
return;
# ifndef BSD4_2
(void) chmod(tt_name, on ? tt_stat.st_mode :
(tt_stat.st_mode & ~S_IEXEC));
# else
(void) fchmod(0, on ? tt_stat.st_mode :
(tt_stat.st_mode & ~S_IEXEC));
# endif
}
#endif /* BIFF */
private void
ttinit()
{
#ifdef BIFF
biff_init();
#endif
#ifdef TIOCSLTC
(void) ioctl(0, TIOCGLTC, (UnivPtr) &ls[OFF]);
ls[ON] = ls[OFF];
ls[ON].t_suspc = (char) -1;
ls[ON].t_dsuspc = (char) -1;
ls[ON].t_flushc = (char) -1;
ls[ON].t_lnextc = (char) -1;
#endif
#if defined(TIOCGETC) && !defined(SYSV)
/* Change interupt and quit. */
(void) ioctl(0, TIOCGETC, (UnivPtr) &tc[OFF]);
tc[ON] = tc[OFF];
tc[ON].t_intrc = IntChar;
tc[ON].t_quitc = (char) -1;
if (OKXonXoff) {
tc[ON].t_stopc = (char) -1;
tc[ON].t_startc = (char) -1;
}
#endif /* TIOCGETC */
do_sgtty();
}
private int done_ttinit = 0;
void
do_sgtty()
{
#ifdef UNIX
# ifdef SYSV
(void) ioctl(0, TCGETA, (char *) &sg[OFF]);
# else
(void) gtty(0, &sg[OFF]);
# endif /* SYSV */
sg[ON] = sg[OFF];
# ifdef LPASS8
(void) ioctl(0, TIOCLGET, (UnivPtr) &lmword[OFF]);
lmword[ON] = lmword[OFF];
if (MetaKey == YES)
lmword[ON] |= LPASS8;
if (HZ)
lmword[ON] &= ~LTILDE;
# endif
# ifdef SYSV
TABS = !((sg[OFF].c_oflag & TAB3) == TAB3);
ospeed = sg[OFF].c_cflag & CBAUD;
if (OKXonXoff)
sg[ON].c_iflag &= ~(IXON | IXOFF);
sg[ON].c_iflag &= ~(INLCR|ICRNL|IGNCR);
sg[ON].c_lflag &= ~(ICANON|ECHO);
sg[ON].c_oflag &= ~(OCRNL|ONLCR);
sg[ON].c_cc[VINTR] = IntChar;
sg[ON].c_cc[VQUIT] = (char) -1;
sg[ON].c_cc[VMIN] = sizeof smbuf;
sg[ON].c_cc[VTIME] = 1;
# else
TABS = !(sg[OFF].sg_flags & XTABS);
sg[ON].sg_flags &= ~XTABS;
ospeed = sg[OFF].sg_ospeed;
# ifdef BRLUNIX
sg[ON].sg_flags &= ~(ECHO | CRMOD);
sg[ON].sg_flags |= CBREAK;
/* VT100 Kludge: leave STALL on for flow control if DC3DC1 (Yuck.) */
sg[ON].sg_xflags &= ~((sg[ON].sg_xflags&DC3DC1 ? 0 : STALL) | PAGE);
# else
sg[ON].sg_flags &= ~(ECHO | CRMOD);
# endif /* BRLUNIX */
# ifdef LPASS8
sg[ON].sg_flags |= CBREAK;
# else
sg[ON].sg_flags |= (MetaKey ? RAW : CBREAK);
# endif
# endif /* SYSV */
#endif /* UNIX */
#ifdef MSDOS
# ifndef IBMPC
setmode(1, 0x8000);
# endif /* IBMPC */
TABS = 0;
#endif /* MSDOS */
}
void
tty_reset()
{
if (!done_ttinit)
return;
ttyset(OFF); /* go back to original modes */
ttinit();
ttyset(ON);
}
/* If n is OFF reset to original modes */
void
ttyset(n)
int n;
{
if (!done_ttinit && n == 0) /* Try to reset before we've set! */
return;
#ifdef UNIX
# ifdef SYSV
(void) ioctl(0, TCSETAW, (UnivPtr) &sg[n]);
# else
# ifdef BRLUNIX
(void) stty(0, &sg[n]);
# else
(void) ioctl(0, TIOCSETN, (UnivPtr) &sg[n]);
# endif /* BRLUNIX */
# endif /* SYSV */
# if defined(TIOCSETC) && !defined(SYSV)
(void) ioctl(0, TIOCSETC, (UnivPtr) &tc[n]);
# endif /* TIOCSETC */
# ifdef TIOCSLTC
(void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[n]);
# endif /* TIOCSLTC */
# ifdef LPASS8
(void) ioctl(0, TIOCLSET, (UnivPtr) &lmword[n]);
# endif
#endif /* UNIX */
#ifdef MSDOS
# ifndef IBMPC
setmode(1, n == 0 ? 0x4000 : 0x8000);
# endif
#endif /* MSDOS */
done_ttinit = 1;
#ifdef BIFF
biff(!n);
#endif
}
int this_cmd,
last_cmd,
LastKeyStruck,
MetaKey = 0;
int
getch()
{
register int c,
peekc;
if (Inputp) {
if ((c = *Inputp++) != '\0')
return LastKeyStruck = c;
Inputp = NULL;
}
if (InJoverc)
return EOF; /* somethings wrong if Inputp runs out while
we're reading a .joverc file. */
#ifndef MSDOS
if (ModCount >= SyncFreq) {
ModCount = 0;
SyncRec();
}
#endif /* MSDOS */
/* If we're not interactive and we're not executing a macro,
AND there are no ungetc'd characters, we read from the
terminal (i.e., getch()). And characters only get put
in macros from inside this if. */
if (((peekc = c = Peekc()) == EOF) &&
(Interactive || ((c = mac_getc()) == EOF))) {
/* So messages that aren't error messages don't
hang around forever. */
if (!UpdMesg && !Asking && mesgbuf[0] != '\0' && !errormsg)
message(NullStr);
redisplay();
#ifdef UNIX
inIOread = 1;
#endif
if ((c = jgetchar()) == EOF)
finish(SIGHUP);
#ifdef UNIX
inIOread = 0;
#endif
if (!Interactive && InMacDefine)
mac_putc(c);
}
if (peekc == EOF) /* don't add_stroke peekc's */
add_stroke(c);
return LastKeyStruck = c;
}
#ifdef UNIX
private void
dorecover()
{
/* Since recover is a normal cooked mode program, reset the terminal */
UnsetTerm(NullStr);
#if defined(IPROCS) && defined(PIPEPROCS)
kbd_kill(); /* kill the keyboard process */
#endif
execl(Recover, "recover", "-d", TmpFilePath, (char *) NULL);
writef("%s: execl failed!\n", Recover);
flusho();
_exit(-1);
/* NOTREACHED */
}
#endif /* UNIX */
void
ShowVersion()
{
s_mess("Jonathan's Own Version of Emacs (%s)", version);
}
private void
UNIX_cmdline(argc, argv)
int argc;
char *argv[];
{
int lineno = 0,
nwinds = 1;
Buffer *b;
ShowVersion();
while (argc > 1) {
if (argv[1][0] != '-' && argv[1][0] != '+') {
int force = (nwinds > 0 || lineno != 0);
#ifdef MSDOS
strlwr(argv[1]);
#endif
minib_add(argv[1], force);
b = do_find(nwinds > 0 ? curwind : (Window *) NULL,
argv[1], force);
if (force) {
SetABuf(curbuf);
SetBuf(b);
if (lineno >= 0)
SetLine(next_line(curbuf->b_first, lineno));
else
SetLine(curbuf->b_last);
if (nwinds > 1)
NextWindow();
if (nwinds)
nwinds -= 1;
}
lineno = 0;
} else switch (argv[1][1]) {
case 'd':
argv += 1;
argc -= 1;
break;
case 'j': /* Ignore .joverc in HOME */
break;
#ifndef MAC
case 'p':
argv += 1;
argc -= 1;
if (argv[1] != NULL) {
SetBuf(do_find(curwind, argv[1], NO));
ErrParse();
nwinds = 0;
}
break;
#endif
case 't':
/* check if syntax is -tTag or -t Tag */
if (argv[1][2] != '\0') {
find_tag(&(argv[1][2]), YES);
} else {
argv += 1;
argc -= 1;
if (argv[1] != NULL)
find_tag(argv[1], YES);
}
break;
case 'w':
if (argv[1][2] == '\0')
nwinds += 1;
else {
int n;
(void) chr_to_int(&argv[1][2], 10, NO, &n);
nwinds += -1 + n;
}
(void) div_wind(curwind, nwinds - 1);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
(void) chr_to_int(&argv[1][1], 10, NO, &lineno);
lineno -= 1;
break;
case 0:
lineno = -1; /* goto end of file ... */
break; /* just like some people's */
} /* favourite editor */
argv += 1;
argc -= 1;
}
}
#ifdef STDARGS
void
error(char *fmt, ...)
#else
/*VARARGS1*/ void
error(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
if (fmt) {
va_init(ap, fmt);
format(mesgbuf, sizeof mesgbuf, fmt, ap);
va_end(ap);
UpdMesg = YES;
}
rbell();
longjmp(mainjmp, ERROR);
}
#ifdef STDARGS
void
complain(char *fmt, ...)
#else
/*VARARGS1*/ void
complain(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
if (fmt) {
va_init(ap, fmt);
format(mesgbuf, sizeof mesgbuf, fmt, ap);
va_end(ap);
UpdMesg = YES;
}
rbell();
longjmp(mainjmp, COMPLAIN);
}
#ifdef STDARGS
void
confirm(char *fmt, ...)
#else
/*VARARGS1*/ void
confirm(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
char *yorn;
va_list ap;
va_init(ap, fmt);
format(mesgbuf, sizeof mesgbuf, fmt, ap);
va_end(ap);
yorn = ask((char *) 0, mesgbuf);
if (*yorn != 'Y' && *yorn != 'y')
longjmp(mainjmp, COMPLAIN);
}
int RecDepth = 0;
void
Recur()
{
char bname[128];
Mark *m;
swritef(bname, "%s", curbuf->b_name);
m = MakeMark(curline, curchar, M_FLOATER);
RecDepth += 1;
UpdModLine = YES;
DoKeys(NO); /* NO means not first time */
UpdModLine = YES;
RecDepth -= 1;
SetBuf(do_select(curwind, bname));
if (!is_an_arg())
ToMark(m);
DelMark(m);
}
#ifdef MAC
jmp_buf auxjmp;
#endif
private int iniargc; /* main sets these for DoKeys() */
private char **iniargv;
private void
DoKeys(firsttime)
int firsttime;
{
int c;
jmp_buf savejmp;
push_env(savejmp);
switch (setjmp(mainjmp)) {
case 0:
if (firsttime)
UNIX_cmdline(iniargc, iniargv);
break;
case QUIT:
if (RecDepth == 0) {
if (ModMacs()) {
rbell();
if (CharUpcase(*ask("No",
"Some MACROS haven't been saved; leave anyway? ")) != 'Y')
break;
}
if (ModBufs(0)) {
rbell();
if (CharUpcase(*ask("No",
"Some buffers haven't been saved; leave anyway? ")) != 'Y')
break;
}
#ifdef IPROCS
KillProcs();
#endif
}
pop_env(savejmp);
return;
case ERROR:
getDOT(); /* God knows what state linebuf was in */
/*FALLTHROUGH*/
case COMPLAIN:
{
gc_openfiles(); /* close any files we left open */
errormsg = YES;
unwind_macro_stack();
Asking = 0;
curwind->w_bufp = curbuf;
DisabledRedisplay = NO;
redisplay();
break;
}
}
this_cmd = last_cmd = 0;
for (;;) {
#ifdef MAC
setjmp(auxjmp);
#endif
if (this_cmd != ARG_CMD) {
clr_arg_value();
last_cmd = this_cmd;
init_strokes();
}
#ifdef MAC
HiliteMenu(0);
EventCmd = 0;
menus_on();
#endif
c = getch();
if (c == EOF)
continue;
dispatch(c);
}
}
int Crashing = 0;
private char **
scanvec(args, str)
register char **args,
*str;
{
while (*args) {
if (strcmp(*args, str) == 0)
return args;
args += 1;
}
return 0;
}
#ifdef UNIX
int UpdFreq = 30,
inIOread = 0;
private SIGRESULT
updmode(junk)
int junk; /* passed in on signal; of no interest */
{
UpdModLine = YES;
if (inIOread)
redisplay();
#ifndef JOB_CONTROL
(void) signal(SIGALRM, updmode);
#endif
(void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
SIGRETURN;
}
#endif /* UNIX */
#ifdef MSDOS
# ifndef IBMPC
char ttbuf[JBUFSIZ];
# endif /* IBMPC */
#endif /* MSDOS */
#if defined(MAC) || (defined(TIOCGWINSZ) && defined(SIGWINCH))
#ifndef MAC
private
#endif
SIGRESULT
win_reshape(junk)
int junk; /* passed in when invoked by a signal; of no interest */
{
register int oldLI;
register int newsize, total;
register Window *wp;
#ifdef UNIX
(void) SigHold(SIGWINCH);
#endif
/*
* Save old number of lines.
*/
oldLI = LI;
/*
* Get new line/col info.
*/
ttsize();
/*
* LI has changed, and now holds the
* new value.
*/
/*
* Go through the window list, changing each window size in
* proportion to the resize. If a window becomes too small,
* delete it. We keep track of all the excess lines (caused by
* roundoff!), and give them to the current window, as a sop -
* can't be more than one or two lines anyway. This seems fairer
* than just resizing the current window.
*/
wp = fwind;
total = 0;
do {
newsize = LI * wp->w_height / oldLI;
if (newsize < 2) {
total += wp->w_height;
wp = wp->w_next;
del_wind(wp->w_prev);
} else {
wp->w_height = newsize;
total += newsize;
wp = wp->w_next;
}
} while (wp != fwind);
curwind->w_height += LI - total - 1;
/* Make a new screen structure */
make_scr();
/* Do a 'hard' update on the screen - clear and redraw */
cl_scr(YES);
flusho();
redisplay();
#ifdef UNIX
(void) signal(SIGWINCH, win_reshape);
#endif
SIGRETURN;
}
#endif
void
#ifdef MAC /* will get args from user, if option key held during launch */
main()
{
int argc;
char **argv;
#else
main(argc, argv)
int argc;
char *argv[];
{
#endif /* MAC */
char *cp;
char ttbuf[MAXTTYBUF];
#ifndef MSDOS
# ifndef VMUNIX
char s_iobuff[LBSIZE],
s_genbuf[LBSIZE],
s_linebuf[LBSIZE];
/* The way I look at it, there ain't no way I is gonna run
out of stack space UNLESS I have some kind of infinite
recursive bug. So why use up some valuable memory, when
there is plenty of space on the stack? (This only matters
on wimpy pdp11's, of course.) */
iobuff = s_iobuff;
genbuf = s_genbuf;
linebuf = s_linebuf;
# endif
#else /* MSDOS */
char *getenv();
#endif /* MSDOS */
#ifdef MAC
MacInit(); /* initializes all */
if(make_cache() == 0) exit(-1);
argc = getArgs(&argv);
#endif /* MAC */
iniargc = argc;
iniargv = argv;
if (setjmp(mainjmp)) {
writef("\rAck! I can't deal with error \"%s\" now.\n\r", mesgbuf);
finish(6);
}
#ifdef MSDOS
/* import the temporary file path from the environment and
fix the string, so that we can append a slash safely */
if (((cp = getenv("TMP")) || (cp = getenv("TMPDIR"))) &&
(*cp != '\0')) {
strcpy(TmpFilePath, cp);
cp = &TmpFilePath[strlen(TmpFilePath)-1];
if ((*cp == '/') || (*cp == '\\'))
*cp = 0;
}
ShFlags[0] = switchar();
#endif /* MSDOS */
getTERM(); /* Get terminal. */
if (getenv("METAKEY"))
MetaKey = 1;
ttsize();
#ifdef MAC
InitEvents();
#else
InitCM();
#endif
d_cache_init(); /* initialize the disk buffer cache */
#ifdef MSDOS
if ((cp = getenv("COMSPEC")) && (*cp != '\0')) {
strcpy(Shell, cp);
}
if ((cp = getenv("DESCRIBE")) && (*cp != '\0'))
strcpy(CmdDb, cp);
#else /* !MSDOS */
#ifndef MAC
if ((cp = getenv("SHELL"))!=NULL && (*cp != '\0')) {
strcpy(Shell, cp);
}
#endif
#endif /* !MSDOS */
make_scr();
mac_init(); /* Initialize Macros */
winit(); /* Initialize Window */
#ifdef IPROCS
pinit(); /* Pipes/process initialization */
#endif
buf_init();
{
char **argp;
if ((argp = scanvec(argv, "-d"))!=NULL
#ifdef UNIX
&& chkCWD(argp[1])
#endif
)
setCWD(argp[1]);
else
getCWD(); /* After we setup curbuf in case we have to getwd() */
}
HomeDir = getenv("HOME");
if (HomeDir == NULL)
HomeDir = "/";
HomeLen = strlen(HomeDir);
#ifdef UNIX
# ifdef SYSV
swritef(Mailbox, "/usr/mail/%s", getenv("LOGNAME"));
# else
swritef(Mailbox, "/usr/spool/mail/%s", getenv("USER"));
# endif
#endif
InitKeymaps();
ttinit(); /* initialize terminal (before ~/.joverc) */
settout(ttbuf); /* not until we know baudrate */
#ifndef MAC
ResetTerm();
#endif
(void) joverc(Joverc); /* system wide .joverc */
cp = 0;
#if defined(MSDOS) || defined(UNIX)
/* If a JOVERC environment variable is set, then use that instead */
if ((cp = getenv("JOVERC")) && (*cp != '\0'))
(void) joverc(cp);
#endif /* MSDOS || UNIX */
if (!scanvec(argv, "-j") && (!cp || *cp == '\0')) {
char tmpbuf[100];
swritef(tmpbuf, "%s/.joverc", HomeDir);
(void) joverc(tmpbuf); /* .joverc in home directory */
}
#ifndef MSDOS
if (scanvec(argv, "-r"))
dorecover();
if (scanvec(argv, "-rc"))
FullRecover();
#endif /* MSDOS */
#ifdef MSDOS
(void) signal(SIGINT, SIG_IGN);
break_off(); /* disable ctrl-c checking */
#endif /* MSDOS */
#ifdef UNIX
(void) signal(SIGHUP, finish);
(void) signal(SIGINT, finish);
(void) signal(SIGBUS, finish);
(void) signal(SIGSEGV, finish);
(void) signal(SIGPIPE, finish);
(void) signal(SIGTERM, SIG_IGN);
# if defined(TIOCGWINSZ) && defined(SIGWINCH)
(void) signal(SIGWINCH, win_reshape);
# endif
/* set things up to update the modeline every UpdFreq seconds */
(void) signal(SIGALRM, updmode);
(void) alarm((unsigned) (UpdFreq - (time((time_t *) 0) % UpdFreq)));
#endif /* UNIX */
cl_scr(1);
flusho();
RedrawDisplay(); /* start the redisplay process. */
DoKeys(YES);
finish(0);
}
#ifdef MSDOS
#include <dos.h>
static char break_state;
/* set the break state to off */
private void
break_off()
{
union REGS regs;
regs.h.ah = 0x33; /* break status */
regs.h.al = 0x00; /* request current state */
intdos(®s, ®s);
break_state = regs.h.dl;
bdos(0x33, 0, 1); /* turn off break */
}
/* reset the break state */
private void
break_rst()
{
bdos(0x33, break_state, 1);
}
#endif